package com.bestcem.xm.ticket.service.manager.notification;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import com.bestcem.xm.componet.redis.service.RedisService;
import com.bestcem.xm.ticket.constant.Constants;
import com.bestcem.xm.ticket.dao.TicketWechatNotificationDao;
import com.bestcem.xm.ticket.entity.mongo.Notification;
import com.bestcem.xm.ticket.enums.NotificationTypeEnum;
import com.bestcem.xm.ticket.grpc.client.TicketBaseUserGrpcService;
import com.bestcem.xm.ticket.grpc.client.dto.user.OrganizationDTO;
import com.bestcem.xm.ticket.service.manager.notify.NotifyManager;
import com.bestcem.xm.ticket.util.NotificationUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Nonnull;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author XiaoYunSong <ys.xiao@idiaoyan.com>
 * @version 通知提醒新增微信公众号
 * @date 2022/4/11 16:10
 */
@Slf4j
@Component
public class WechatPublicManager {

    @Resource
    private NotifyManager notifyUtil;
    @Resource
    private NotificationUtil notificationUtil;

    @Resource
    private TicketWechatNotificationDao ticketWechatNotificationDao;

    @Autowired
    private RedisService redisService;

    @Resource
    private TicketBaseUserGrpcService ticketBaseUserGrpcService;

    /**
     * 每天每份问卷发送消息上限
     */
    @Value("${app.ticket.notification.wechat-public-send-limit:500}")
    Integer wechatPublicSendLimit;
    /**
     * 微信公众号模板id
     */
    @Value("${app.ticket.notification.wechat-public-template-id:500}")
    String wechatPublicTemplateId;
    /**
     * 协议配置
     */
    @Value("${app.ticket.notify-protocol:https}")
    private String notifyProtocol;
    /**
     * 服务器配置
     */
    @Value("${app.ticket.notify-url:bestcem.com}")
    private String notifyUrl;


    /**
     * 发送 通知提醒微信公众号模板消息
     *
     * @param notification 通知提醒
     * @param projectName  项目名称
     * @param type         通知提醒类型
     * @param typeTag      限制资源标记
     * @param seq          答卷seq
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/4/11 16:30
     */
    public void sendWechatPublicNotification(Notification notification, String projectName,
                                             NotificationTypeEnum type, String typeTag, Long seq) {
        if (Objects.isNull(notification) || Objects.isNull(notification.getWays()) || !Boolean.TRUE.equals(notification.getWays().getWechatPublicEnable())) {
            return;
        }

        // 每天每份问卷发送的消息有限制
        String limitKey = getLimitKey(notification.getId());
        Long increment = redisService.incr(limitKey);
        if (Objects.nonNull(increment) && increment == 1L) {
            redisService.expire(limitKey, 24, TimeUnit.HOURS);
        }
        if (Objects.nonNull(increment) && increment > wechatPublicSendLimit) {
            if (log.isInfoEnabled()) {
                log.info("[Ticket] 问卷 {}-{} 今日通知提醒微信公众号发送消息已达上限", notification.getSurveyId(), projectName);
            }
            return;
        }

        List<String> openIds = ticketWechatNotificationDao.listNotificationSubscriberOpenIds(notification.getSurveyId());

        String title = TitleTemplate.getTitle(type);
        Map<String, String> messageData = getData(notification, type, typeTag);
        String content = formatTemplate(ContentTemplate.getContent(type), messageData);
        // 自定义参数
        Map<String, Item> params = new HashMap<>();
        // 标题
        params.put("first", new Item(title, "#888888"));
        // 项目名称
        params.put("keyword1", new Item(projectName, "#191919"));
        // 描述
        params.put("keyword2", new Item(content, "#191919"));
        // 填充字段
        params.put("keyword3", new Item("无", "#191919"));
        // 填充字段
        params.put("keyword4", new Item("无", "#191919"));

        String url = null;
        OrganizationDTO organizationDTO = ticketBaseUserGrpcService.getOrganization(notification.getOrgId());
        String orgCode = null;
        if (Objects.nonNull(organizationDTO)) {
            orgCode = organizationDTO.getCode();
        }
        if (NotificationTypeEnum.FIRST_RSPD.equals(type)
                || NotificationTypeEnum.EVERY_RSPD.equals(type)) {
            // 展示答卷详情
            url = getSurveyDetailUrl(notification.getSurveyId(), seq, orgCode);
        } else if (NotificationTypeEnum.REACH_RSPD.equals(type)
                || NotificationTypeEnum.FREQ_RSPD.equals(type)
                || NotificationTypeEnum.RATIO_RSPD.equals(type)) {
            // 展示问卷数据
            url = getSurveyDataUrl(notification.getSurveyId(), orgCode);
        }
        notifyUtil.sendWechatPublic(openIds, wechatPublicTemplateId, JSON.toJSONString(params), url);
    }


    /**
     * 渲染 微信公众号模板消息描述需要的数据
     *
     * @param notification 通知提醒
     * @param typeTag      限制资源标记
     * @return 自定义数据
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/4/11 16:30
     */
    @Nonnull
    private Map<String, String> getData(Notification notification, NotificationTypeEnum type, String typeTag) {
        Map<String, String> result = new HashMap<>();

        // 回收频次 时间区间
        result.put(FiledConstant.FREQ_TIME, NotificationUtil.TIME_OPERATOR_2_TXT.get(notification.getRule().getFreqTime()));
        // 回收环比 时间区间
        result.put(FiledConstant.RATIO_TIME, NotificationUtil.TIME_OPERATOR_2_TXT.get(notification.getRule().getRatioTime()));
        // 回收数量 数量
        result.put(FiledConstant.REACH_NUMBER, String.valueOf(notification.getRule().getReachCount()));
        // 回收频次 数量
        result.put(FiledConstant.FREQ_NUMBER, String.valueOf(notification.getRule().getFreqValue()));
        // 回收环比 百分比
        result.put(FiledConstant.RATIO_PERCENTAGE, String.valueOf(notification.getRule().getRatioValue()));
        // 回收频次 比较符
        result.put(FiledConstant.FREQ_OPERATOR, NotificationUtil.COMPARE_OPERATOR_2_TXT.get(notification.getRule().getFreqOperator()));
        // 回收环比 比较符
        result.put(FiledConstant.RATIO_OPERATOR, NotificationUtil.COMPARE_OPERATOR_2_TXT.get(notification.getRule().getRatioOperator()));
        // 配额名称
        if (NotificationTypeEnum.QUOTE_FULL.equals(type)) {
            result.put(FiledConstant.QUOTE_TITLE, notificationUtil.getQuoteTitle(typeTag));
        }
        // 奖励名称
        if (NotificationTypeEnum.BONUS_AWARD.equals(type) || NotificationTypeEnum.DRAW_AWARD.equals(type)) {
            result.put(FiledConstant.AWARD_TITLE, notificationUtil.getAwardTitle(typeTag));
        }

        return result;
    }


    /**
     * 获取答卷详情URL
     *
     * @param surveyId 问卷id
     * @param seq      答卷seq
     * @param orgCode  租户code
     * @return 答卷详情URL
     * @date 2022/4/13 18:42
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     */
    private String getSurveyDetailUrl(String surveyId, Long seq, String orgCode) {
        StringBuilder urlBuilder = new StringBuilder();
        if (!ObjectUtils.isEmpty(orgCode)) {
            urlBuilder.append(getOrgUrl(orgCode));
        } else {
            urlBuilder.append(notifyProtocol);
            urlBuilder.append("://");
            urlBuilder.append(notifyUrl);
        }
        urlBuilder.append("/record/");
        urlBuilder.append(surveyId);
        urlBuilder.append("/surveyviewtable?source=wechat&mtype=detail&seq=");
        urlBuilder.append(seq);
        return urlBuilder.toString();
    }


    /**
     * 获取问卷数据URL
     *
     * @param surveyId 问卷id
     * @param orgCode  租户code
     * @return 问卷数据URL
     * @date 2022/4/13 18:42
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     */
    private String getSurveyDataUrl(String surveyId, String orgCode) {
        StringBuilder urlBuilder = new StringBuilder();
        if (!ObjectUtils.isEmpty(orgCode)) {
            urlBuilder.append(getOrgUrl(orgCode));
        } else {
            urlBuilder.append(notifyProtocol);
            urlBuilder.append("://");
            urlBuilder.append(notifyUrl);
        }
        urlBuilder.append("/record/");
        urlBuilder.append(surveyId);
        urlBuilder.append("/surveyviewtable?source=wechat&mtype=report");
        return urlBuilder.toString();
    }


    /**
     * 获取制定公司的域名 orgcode.xxx.com，考虑到私有部署的情况做了一些调整
     *
     * @param orgCode 公司 code
     * @return String
     * @author gy.liu
     * @date 2021/8/23
     */
    @Nonnull
    private String getOrgUrl(String orgCode) {
        StringBuilder url = new StringBuilder();
        url.append(notifyProtocol);
        url.append("://");
        if (!ObjectUtils.isEmpty(orgCode) && !Constants.BLANK.equals(orgCode)) {
            url.append(orgCode);
            url.append(".");
        }
        url.append(notifyUrl);
        return url.toString();
    }


    /**
     * 模板格式化
     *
     * @param template 通知模板
     * @param data     模板填充数据
     * @return 填充完成的内容
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/4/11 16:50
     */
    private static String formatTemplate(String template, @Nonnull Map<String, String> data) {
        if (ObjectUtils.isEmpty(template)) {
            return Constants.BLANK;
        }
        String result = template;
        for (String field : data.keySet()) {
            String value = data.get(field);
            if (ObjectUtils.isEmpty(value)) {
                value = " ";
            }
            result = result.replace(field, value);
        }
        return result;
    }


    /**
     * 获取通知提醒每日发送微信公众号通知数量上限缓存key
     *
     * @param notificationId 通知提醒id
     * @return 缓存key
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/4/13 17:53
     */
    private static String getLimitKey(String notificationId) {
        String format = LocalDate.now().format(DateTimeFormatter.ofPattern("MMdd"));
        return "ticket.notification.wechat." + format + "." + notificationId;
    }

    /**
     * 微信公众号模板消息自定义数据字段
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Item {
        /**
         * 字段值
         */
        @JSONField(name = "value")
        private String value;
        /**
         * 字体颜色
         */
        @JSONField(name = "color")
        private String color;
    }
}
